BITS 32
%include "macrosmodoprotegido.mac"

;====================================================================
;                           MACROS UTILES
;====================================================================

;=============
; PRINT_LINEA
; %1 mensaje
; %2 fila
; %3 col
;=============
%macro PRINT_LINEA 3
    ;Imprime titulo
    IMPRIMIR_TEXTO reg_%1, 3, 0x07, %2, %3
    
    ;Imprime valor
    PRINT_HEXA %1, %2, %3+10
%endmacro

;=============
; PRINT_HEXA
; %1 mensaje
; %2 fila
; %3 col
;=============
tmp: dd 0h, 0h          ; 8 digitos ascii
%macro PRINT_HEXA 3
    DWORD_TO_HEX %1, tmp
    IMPRIMIR_TEXTO tmp, 8, 0x07, %2, %3
%endmacro

extern fin_intr_pic1

;==================
; DEFINIR_HANDLER
; %1 mensaje
; %2 fila
; %3 col
;==================
%macro DEFINIR_HANDLER 1
global _isr%1
_isr%1:
    xchg bx, bx
    IMPRIMIR_TEXTO msg%1, msg%1_len, 0x07, 1, 1
    call dump_pantalla
    jmp $
%endmacro


;====================================================================
;                MENSAJES PARA IMPRIMIR EN PANTALLA
;====================================================================

msg0: db 'Fault: (#DE) Division by zero Exception'
msg0_len: equ $-msg0

msg1: db 'Fault: (#DB) Debug Exception'
msg1_len: equ $-msg1

msg2: db 'Interrupt: (NMI) Non-maskeable External Interrupt Exception'
msg2_len: equ $-msg2

msg3: db 'Trap: (#BP) Breakpoint Exception'
msg3_len: equ $-msg3

msg4: db 'Trap: (#OF) Overflow Exception'
msg4_len: equ $-msg4

msg5: db 'Fault: (#BR) BOUND Range Exceeded Exception'
msg5_len: equ $-msg5

msg6: db 'Fault: (#UD) Invalid Opcode Exception'
msg6_len: equ $-msg6

msg7: db 'Fault: (#NM) No Math Coprocessor Exception'
msg7_len: equ $-msg7

msg8: db 'Abort: (#DF) Double Fault Exception'
msg8_len: equ $-msg8

msg9: db 'Fault: (#MF) CoProcessor Segment Overrun Exception'
msg9_len: equ $-msg9

msg10: db 'Fault: (#TS) Invalid TSS Exception'
msg10_len: equ $-msg10

msg11: db 'Fault: (#NP) Segment Not Present Exception'
msg11_len: equ $-msg11

msg12: db 'Fault: (#SS) Stack Segment Exception'
msg12_len: equ $-msg12

msg13: db 'Fault: (#GP) General Protection Fault Exception'
msg13_len: equ $-msg13

msg14: db 'Fault: (#PF) Page Fault Exception'
msg14_len: equ $-msg14

msg15: db ' (RVD) "Reserved" Exception'
msg15_len: equ $-msg15

msg16: db 'Fault: (#MF) Floating-Point Error Exception'
msg16_len: equ $-msg16

msg17: db 'Fault: (#AC) Alignment Check Exception'
msg17_len: equ $-msg17

msg18: db 'Abort: (#MC) Machine Check Exception'
msg18_len: equ $-msg18

msg19: db 'Fault: (#XF) SIMD Floating-Point Exception'
msg19_len: equ $-msg19

reg_eax: db 'EAX'
reg_ebx: db 'EBX'
reg_ecx: db 'ECX'
reg_edx: db 'EDX'
reg_esi: db 'ESI'
reg_edi: db 'EDI'
reg_ebp: db 'EBP'
reg_esp: db 'ESP'
reg_ds: db 'DS '
reg_cs: db 'CS '
reg_es: db 'ES '
reg_fs: db 'FS '
reg_gs: db 'GS '
reg_ss: db 'SS '
reg_cr0: db 'CR0'
reg_cr2: db 'CR2'
reg_cr3: db 'CR3'
reg_cr4: db 'CR4'
reg_eflags: db  'EFLAGS'
stack: db  'STACK'
backtrace: db  'BACKTRACE'
isrcortesia: db 'Cortesia de Angiulino "El Chino" Cubrepileta'
isrcortesia_len: equ $-isrcortesia

;datos para cambio de tarea
tick: dd 0
offset: dd 0
selector: dw 0

extern isrnombregrupo, isrnombregrupo_len, proxima_tarea, eliminar_proceso, tarea_actual, duplicar_proceso, eliminar_proceso, chess
;==============================================================
;      DEFINICION DE HANDLERS
;==============================================================
DEFINIR_HANDLER 0
DEFINIR_HANDLER 1
DEFINIR_HANDLER 2
DEFINIR_HANDLER 3
DEFINIR_HANDLER 4
DEFINIR_HANDLER 5
DEFINIR_HANDLER 6
DEFINIR_HANDLER 7
DEFINIR_HANDLER 8
DEFINIR_HANDLER 9
DEFINIR_HANDLER 10
DEFINIR_HANDLER 11
DEFINIR_HANDLER 12
DEFINIR_HANDLER 13
DEFINIR_HANDLER 14
DEFINIR_HANDLER 15
DEFINIR_HANDLER 16
DEFINIR_HANDLER 17
DEFINIR_HANDLER 18
DEFINIR_HANDLER 19

;=====================================================
; RUTINAS DE ATENCION DE INTERRUPCIONES DE HARDWARE
;=====================================================
; ATENCION RELOJ
global _isr32
_isr32:
    pushad
    pushfd
    call fin_intr_pic1

    inc dword [tick]            ; incrementamos tick
    call proximo_reloj          ; actualizamos animacion

    call proxima_tarea
    
    cmp ax, 0
    je fin_reloj
    mov [selector], ax
    
    ;~ xchg bx, bx
    jmp far [offset]            ; cambia tarea
    jmp fin_reloj
    
fin_reloj:
    popfd
    popad
    iret

; ATENCION TECLADO
global _isr33
_isr33:
    pushad
    pushfd
    call fin_intr_pic1

    mov ax, 0x0700          ; color para el caracter: Blanco sobre negro
    
    in al, 0x60             ; leo del buffer del teclado            
    bt ax, 7                
    jc fin_teclado          ; if(break code) return

    push eax
    call chess
    pop eax
    
    cmp al, 0x2             ; if(code < tecla_1) return
    jb fin_teclado
    
    cmp al, 0xB             
    ja fin_teclado          ; if(code > tecla_0) return
    jne imprimir_numeros    ; if(code = tecla_0) imprimo 0
    mov al, 0x0             ; imprime la tecla 0
    jmp escribe_tecla
    
imprimir_numeros:    
    dec al                     ; calcula el pid como tecla-1
    
escribe_tecla:

    and eax, 0xFF           ; Calcula el pid a partir del ascii
    push eax
    call eliminar_proceso
    add esp, 4
    
    
fin_teclado:
    popfd
    popad
    iret
    
global _isr66
_isr66:
    pushad
    pushfd
    call fin_intr_pic1

    call duplicar_proceso
    
    popfd
    popad

    iret    
    jmp _isr66
    
global _isr77
_isr77:
    pushad
    pushfd
    call fin_intr_pic1
    
    call eliminar_proceso
    
    popfd
    popad
    mov eax, 0    
    iret

global _isr88
_isr88:
    pushad
    pushfd
    call fin_intr_pic1

    popfd
    popad
    mov eax, [tarea_actual]
    iret    

global _isr99
_isr99:
    pushad
    pushfd
    call fin_intr_pic1

    popfd
    popad
    mov eax, [tick]
    iret

;==============================================================
;      RUTINA QUE IMPRIME LOS REGISTROS EN PANTALLA
;==============================================================
dump_pantalla:
    pushfd                      ; es lo primero que hago asi no se modifica
    
    ; TIPO DE INTERRUPCION
    ;===========
    ; TODO: imprimir el tipo de interrupcion
    ;===========
    
    ; REGISTROS DE PROPOSITO GENERAL 
    ;  usamos PRINT_LINEA %mensaje, %fila, %col
	PRINT_LINEA eax, 3, 1
    PRINT_LINEA ebx, 4, 1
    PRINT_LINEA ecx, 5, 1
    PRINT_LINEA edx, 6, 1
    PRINT_LINEA esi, 7, 1
    PRINT_LINEA edi, 8, 1
    PRINT_LINEA esp, 9, 1
    PRINT_LINEA ebp, 10, 1

    ; REGISTROS DE SEGMENTO
    PRINT_LINEA cs, 3, 26
    PRINT_LINEA ds, 4, 26
    PRINT_LINEA es, 5, 26
    PRINT_LINEA fs, 6, 26
    PRINT_LINEA gs, 7, 26    
    PRINT_LINEA ss, 8, 26    
    
    ; REGISTROS DE CONTROL
    PRINT_LINEA cr0, 12, 1
    PRINT_LINEA cr2, 13, 1
    PRINT_LINEA cr3, 14, 1
    PRINT_LINEA cr4, 15, 1
    
    ; EFLAGS
    IMPRIMIR_TEXTO reg_eflags, 6, 0x07, 17, 1
    pop eax
    PRINT_HEXA eax, 17, 1+10
    
    ;STACK
    IMPRIMIR_TEXTO stack, 5, 0x07, 10, 26
    mov eax, [esp+4]          ;empiezo en 4 para no mostrar la direccion de retorno de esta funcion
    PRINT_HEXA eax, 12, 26
    mov eax, [esp+8]        
    PRINT_HEXA eax, 13, 26
    mov eax, [esp+12]
    PRINT_HEXA eax, 14, 26
    mov eax, [esp+16]
    PRINT_HEXA eax, 15, 26
    mov eax, [esp+20]
    PRINT_HEXA eax, 16, 26
    mov eax, [esp+24]
    PRINT_HEXA eax, 17, 26   
    
    ;BACKTRACE
    IMPRIMIR_TEXTO backtrace, 9, 0x07, 10, 47

    ; Primer direccion de retorno
    mov eax, [esp+16]                            ;empiezo en 4 para no mostrar la direccion de retorno de esta funcion
    PRINT_HEXA eax, 12, 47
    
    
    ; empiezo desde la 12 pero en paralelo con lo otro me corro seis columnas
	mov ecx, 13             ; fila de impresion
	mov ebx, 0
    mov esi, ebp
    xchg bx, bx
	; imprimo el backtrace
	.ciclo_imprimir_btrace:
		cmp esi, 0x17000
		je .btrace_fin
        cmp esi, 0x30000
		je .btrace_fin
		cmp ebx, 4
		je .btrace_fin

		; en ebp + 4 esta el codigo de retorno, lo imprimo
		mov eax, [esi + 4]
		PRINT_HEXA eax, ecx, 47

		; cargo el ebp anterior
        mov esi, [esi]

		inc ebx
		inc ecx
		jmp .ciclo_imprimir_btrace
	.btrace_fin:
    
    ; IMPRIME A NUESTRO GUIA ESPIRITUAL
    IMPRIMIR_TEXTO isrcortesia, isrcortesia_len, 0x0A, 22, 35
    
    ret


proximo_reloj:
	pushad
	inc DWORD [isrnumero]
	mov ebx, [isrnumero]
	cmp ebx, 0x4
	jl .ok
		mov DWORD [isrnumero], 0x0
		mov ebx, 0
	.ok:
		add ebx, isrmensaje1
		mov edx, isrmensaje
		IMPRIMIR_TEXTO edx, 6, 0x0A, 24, 73
		IMPRIMIR_TEXTO ebx, 1, 0x0A, 24, 79
	popad
	ret
	
isrmensaje: db 'Clock:'
isrnumero: dd 0x00000000
isrmensaje1: db '|'
isrmensaje2: db '/'
isrmensaje3: db '-'
isrmensaje4: db '\'




